package gmu.swe.project.tracker;

import gmu.swe.project.peer.PeerInfo;
import gmu.swe.project.utils.Helper;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import static java.util.concurrent.TimeUnit.*;

public class TrackerKeepAliveService extends Thread {

	int interval = 0;
	final ScheduledExecutorService scheduler = Executors
			.newScheduledThreadPool(1);
	private static final String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss";
	SimpleDateFormat dfm = new SimpleDateFormat(DATE_FORMAT_NOW);

	TrackerKeepAliveService(int intervalArg) {
		super("TrackerKeepAliveService");
		this.interval = intervalArg;
	}// TrackerKeepAliveService

	public void run() {

		System.out.println("TrackerKeepAliveService::run()::TrackerKeepAliveService thread spawned");

		checkPeerRegistration();
	}// run

	/**
	 * The scheduler that is currently set to start immediately, and execute
	 * every X seconds. The process is to check the current peer registration
	 * and make sure that all current peers have sent a keep alive message
	 * within the last X seconds, if any peers did not send a message within
	 * the time-frame, those peers will be removed from the peer
	 * registration and considered no longer on the network
	 */
	public void checkPeerRegistration() {
		final Runnable keepAlive = new Runnable() {
			
			public void run() {
				Date time = Helper.getCurrTime();
				System.out.println("****************************************");
				System.out.println("TrackerKeepAliveService::run()::Check PeerRegistration every "
								+ Integer.toString(interval) + " seconds");
				System.out.println("TrackerKeepAliveService::run()::Current time: "
								+ dfm.format(time));
				processPeerRegistration(time);	
				Tracker.peerRegistration.printMe();
			}
		};
		scheduler.scheduleAtFixedRate(keepAlive, 0, interval, SECONDS);

	}// checkPeerRegistration

	/**
	 * Iterate through the main peer registration and check the time-stamp of
	 * each peer, ensuring that each peer has a valid time-stamp within
	 * the last "X" seconds
	 */
	private void processPeerRegistration(Date currTime) {
		System.out.println("TrackerKeepAliveService::processPeerRegistration()");
		PeerRegistration tmpPr = Tracker.peerRegistration;
		boolean dirty = false;

		Iterator<PeerInfo> trIter = tmpPr.iterator();
		while (tmpPr.getPeerSet().size() > 0 && trIter.hasNext()) {
			PeerInfo peer = (PeerInfo) trIter.next();
			Date trackerTime = peer.getTimestamp();
			if (Helper.compareTime(currTime.getTime(), trackerTime.getTime()) > interval) {
				System.out.println("TrackerKeepAliveService::processPeerRegistration():found OUT-DATED peer");
				dirty = true;
				tmpPr.removePeer(peer);
				//decrement the workload
				Integer workload = Tracker.trackerInfo.getWorkload();
				int workInt = workload.intValue();
				workInt--;
				Tracker.trackerInfo.setWorkload(new Integer(workInt));
			}
		}// while
		if (dirty) {
			System.out.println("TrackerKeepAliveService::processPeerRegistration():reset the peer registration");
			Tracker.peerRegistration = tmpPr;
		}
		System.out.println("TrackerKeepAliveService::processPeerRegistration():Done processing");
	}// processPeerRegistration

}// class TrackerKeepAliveService
